<?php

declare (strict_types = 1);

namespace owns\library;

use Firebase\JWT\BeforeValidException;
use Firebase\JWT\ExpiredException;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use Firebase\JWT\SignatureInvalidException;
use InvalidArgumentException;
use owns\enum\RespCode;
use think\facade\Config;
use TypeError;
use UnexpectedValueException;

/**
 * token 校验
 */
class OwnsJwtAuth
{
    // 类型
    const TYPE = 'JWT';
    // 签名算法
    const ALG = 'HS256';
    // 密钥
    const KEY = 'ZXGJHZfb9EvcCfVpHo5u93BzQj3I6B7n';
    // 过期时间
    public $expire;
    
    public function __construct()
    {
        $this->expire = Config::get('jwt.ttl');
    }
    /**
     * 获取签名
     */
    public function sign(array $user)
    {
        $payload = [
            "iss" => "system", // JWT的签发者
            "sub" => 'user', // 面向用户
            "iat" => time(), // 签发时间
            "exp" => time() + $this->expire, // 过期时间
            "nbf" => time(), // 时间之前不处理
            "jti" => md5(uniqid(self::TYPE) . time()), // token唯一标识
            "data" => $user,
        ];
        return JWT::encode($payload, self::KEY, self::ALG);
    }
    /**
     * 验证token
     */
    public function verify(string $token)
    {
        try {
            $decoded = JWT::decode($token, new Key(self::KEY, self::ALG));
            if ($decoded->exp < time()) {
                tips('请重新登录', RespCode::NOT_LOGIN);
            }
            return $decoded->data;
        } catch (InvalidArgumentException) {
            return false;
        } catch (UnexpectedValueException) {
            return false;
        } catch (SignatureInvalidException) {
            return false;
        } catch (BeforeValidException) {
            return false;
        } catch (ExpiredException) {
            return false;
        } catch (TypeError) {
            return false;
        }
    }
    /**
     * 刷新token
     */
    public function refresh(string $token, array $ui = [])
    {
        try {
            $res = $this->verify($token);
            $new_ui = $ui ? $ui : $res;
            return $this->sign($new_ui);
        } catch (ExpiredException $e) {
        }
    }
    /**
     * 获取token的id
     */
    public function uid()
    {
        $token = request()->header();
        if (!isset($token['authorization'])) {
            return 0;
        }
        $data = $this->verify(str_replace('Bearer ', '', $token));
        return $data ? $data['id'] : 0;
    }
}
